// 文件路径: dbms/execution/execution/OrderByExecutor.java (这是一个新文件)
package com.dbms.execution.execution;

import com.dbms.common.Schema;
import com.dbms.common.Tuple;
import com.dbms.execution.plan.PlanNode;
import com.dbms.parser.ast.OrderByNode;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

/**
 * OrderByExecutor (排序执行器) 负责对子执行器的输出结果进行排序。
 * 这是一个典型的 **阻塞式 (blocking)** 执行器，因为它必须先从其子执行器
 * 接收并缓存所有的元组，然后才能对它们进行排序，最后才能开始输出第一个结果。
 */
public class OrderByExecutor implements Executor {

    private final Executor child; // 提供待排序数据的子执行器
    private final OrderByNode orderByNode; // 包含排序信息的 AST 节点
    private List<Tuple> sortedTuples; // 存储排序后结果的列表
    private Iterator<Tuple> tupleIterator; // 用于遍历排序结果的迭代器

    public OrderByExecutor(Executor child, OrderByNode orderByNode) {
        this.child = child;
        this.orderByNode = orderByNode;
    }

    /**
     * open() 方法是这个执行器的核心。它执行了所有阻塞式操作。
     */
    @Override
    public void open() {
        child.open();
        // 1. 【阻塞点】从子执行器拉取所有元组并存储在内存列表中。
        List<Tuple> childTuples = new ArrayList<>();
        Tuple tuple;
        while ((tuple = child.next()) != null) {
            childTuples.add(tuple);
        }
        child.close(); // 子执行器的数据已经全部消耗完毕，可以提前关闭。

        // 2. 确定用于排序的列（sort key）及其在元组中的索引。
        // 为了简化，我们暂时只支持按第一个指定的列进行排序。
        String sortKeyColumn = orderByNode.getColumns().get(0);
        Schema schema = getSchema();
        int sortKeyIndex = -1;
        for (int i = 0; i < schema.getColumnCount(); i++) {
            if (schema.getColumn(i).getColumnName().equalsIgnoreCase(sortKeyColumn)) {
                sortKeyIndex = i;
                break;
            }
        }

        if (sortKeyIndex == -1) {
            throw new RuntimeException("ORDER BY column '" + sortKeyColumn + "' not found in result set.");
        }

        final int finalSortKeyIndex = sortKeyIndex;
        // 3. 创建一个比较器 (Comparator) 来定义排序规则。
        //    使用 Lambda 表达式可以非常简洁地实现。
        Comparator<Tuple> comparator = (t1, t2) -> {
            // 我们假设用于排序的列的值都是可比较的（实现了 Comparable 接口）
            @SuppressWarnings("unchecked")
            Comparable<Object> val1 = (Comparable<Object>) t1.getValue(finalSortKeyIndex);
            Object val2 = t2.getValue(finalSortKeyIndex);
            return val1.compareTo(val2);
        };

        // 4. 如果是 DESC（降序），则反转比较器的顺序。
        if (orderByNode.getOrder().equalsIgnoreCase("DESC")) {
            comparator = comparator.reversed();
        }

        // 5. 执行排序。
        childTuples.sort(comparator);
        this.sortedTuples = childTuples;
        // 6. 创建迭代器，为 next() 方法做准备。
        this.tupleIterator = this.sortedTuples.iterator();
    }

    /**
     * 从已排序的结果列表中返回下一个元组。
     */
    @Override
    public Tuple next() {
        if (tupleIterator != null && tupleIterator.hasNext()) {
            return tupleIterator.next();
        }
        return null;
    }

    /**
     * 关闭执行器，释放对排序后元组列表的引用，以便垃圾回收。
     */
    @Override
    public void close() {
        this.sortedTuples = null;
        this.tupleIterator = null;
    }

    @Override
    public Schema getSchema() {
        // 排序操作不改变元组的模式，所以直接返回子执行器的模式。
        return child.getSchema();
    }

    @Override
    public PlanNode getPlanNode() {
        // 为 EXPLAIN ANALYZE 创建计划节点。
        // 由于这是一个阻塞执行器，它的主要开销发生在 open() 阶段的排序过程。
        // 一个更复杂的实现会在这里估算并记录排序的成本。
        PlanNode node = new PlanNode("Sort", "on " + orderByNode.getColumns() + " " + orderByNode.getOrder());
        // 递归获取子执行器的计划节点
        node.addChild(child.getPlanNode());
        return node;
    }
}